package classfile

type ClassFile struct {
	magic             uint32          // 魔数
	minorVersion      uint16          // 副版本
	majorVersion      uint16          // 主版本
	constantPoolCount uint16          // 常量池计数
	constantPool      ConstantPool    // 常量池，池中每一项都是tag（指定下一个常量的类型）+结构体（常量的实际值）
	accessFlags       uint16          // 这个类的访问标志
	thisClass         uint16          // 这个类在常量池中的索引位置
	superClass        uint16          // 超类在常量池中的索引位置
	interfaceCount    uint16          // 实现的接口数量
	interfaces        []uint16        // 实现的接口在常量池中的索引
	fieldsCount       uint16          // 字段数量
	fields            []*MemberInfo   // 此类中的字段，不是索引，直接就是field_info结构体
	methodsCount      uint16          // 方法数量
	methods           []*MemberInfo   // 此类中的方法，直接是结构体
	attributorCount   uint16          // 属性计数
	attributes        []AttributeInfo // 此类的属性，字节码就是放在这，还有一些其他的东西，比如异常表，是一个结构体数组
}

func Parse(classData []byte) (cf *ClassFile, err error) {
	// 匿名函数，在此方法退出时执行
	// 如果函数中出现了错误，这个方法会捕获错误，并且让程序继续执行
	//defer func() {
	//	if r := recover(); r != nil {
	//		var ok bool
	//		err, ok := r.(error)
	//		if !ok {
	//			err = fmt.Errorf("%v", r)
	//			fmt.Println(err)
	//			panic(err)
	//		}
	//	}
	//}()
	// 构造一个新的阅读器，用于读取class文件
	cr := &ClassReader{classData}
	// 新建一个结构体用于保存解析后的class文件
	cf = &ClassFile{}
	// 解析class文件
	cf.read(cr)
	return cf, nil
}
func (self *ClassFile) read(reader *ClassReader) {
	// 先检查魔数，class文件的前4个字节是魔数
	self.readAndCheckMagic(reader)
	// 检查版本，接下来四个字节是主版本和副版本
	self.readCheckVersion(reader)
	// 接下来是常量池
	self.constantPool = readConstantPool(reader)
	// 访问标识
	self.accessFlags = reader.ReadUint16()
	self.thisClass = reader.ReadUint16()
	self.superClass = reader.ReadUint16()
	// 实现的接口在常量池索引的数组
	self.interfaces = reader.ReadUint16s()
	// 读取字段和方法，都是先给出数量，然后读取实际的值。并且值是一个结构体
	self.fields = readMembers(reader, self.constantPool)
	self.methods = readMembers(reader, self.constantPool)
	// 读取属性表
	self.attributes = readAttributes(reader, self.constantPool)

}

// Class文件要求以CAFEBABE开头
func (self *ClassFile) readAndCheckMagic(reader *ClassReader) {
	// class文件的前4个字节是魔数
	magic := reader.ReadUint32()
	if magic != 0xCAFEBABE {
		panic("java.lang.ClassFormatError : magic")
	}
}

/*
 * 解析并且保存主版本号和副版本号
 */
func (self *ClassFile) readCheckVersion(reader *ClassReader) {
	// 副版本号
	self.minorVersion = reader.ReadUint16()
	// 主版本号
	self.majorVersion = reader.ReadUint16()
	// 仿照JDK8，支持45-52版本的class文件
	switch self.majorVersion {
	case 45:
		return
	case 46, 47, 48, 49, 50, 51, 52:
		if self.minorVersion == 0 {
			return
		}
	}
	panic("java.lang.UnsupportedClassVersionError")

}

func (self *ClassFile) ClassName() string {
	return self.constantPool.getClassName(self.thisClass)
}

func (self *ClassFile) SuperClassName() string {
	if self.superClass > 0 {
		return self.constantPool.getClassName(self.superClass)
	}
	return ""
}

func (self *ClassFile) InterfaceNames() []string {
	interfaceNames := make([]string, len(self.interfaces))
	for i, cpIndex := range self.interfaces {
		interfaceNames[i] = self.constantPool.getClassName(cpIndex)
	}
	return interfaceNames
}

// get方法
func (self *ClassFile) MinorVersion() uint16 {
	return self.minorVersion
}
func (self *ClassFile) MajorVersion() uint16 {
	return self.majorVersion
}
func (self *ClassFile) ConstantPool() ConstantPool {
	return self.constantPool
}
func (self *ClassFile) AccessFlags() uint16 {
	return self.accessFlags
}
func (self *ClassFile) Fields() []*MemberInfo {
	return self.fields
}
func (self *ClassFile) Methods() []*MemberInfo {
	return self.methods
}
